<pre class='metadata'>
Title: CSS Positioned Layout Module Level 3
Status: ED
Work Status: Refining
Shortname: css-position
Level: 3
Group: csswg
ED: https://drafts.csswg.org/css-position-3/
TR: https://www.w3.org/TR/css-position-3/
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Tab Atkins Jr., Google, http://xanthir.com/contact/, w3cid 42199
Former Editor: Rossen Atanassov, Microsoft, ratan@microsoft.com, w3cid 49885
Former Editor: Arron Eicholz, Microsoft, arronei@microsoft.com, w3cid 37934
!Feedback: <a href="http://wiki.csswg.org/spec/css-position/">in Wiki</a>
Abstract: This module contains defines coordinate-based positioning and offsetting schemes of <a href="https://www.w3.org/TR/CSS/">CSS</a>: [=relative positioning=], [=sticky positioning=], [=absolute positioning=], and [=fixed positioning=].
Link Defaults: css-transforms-1 (property) transform
</pre>
<pre class=link-defaults>
spec:css-writing-modes-4; type:dfn; text:end
spec:css2; type:value; for:float; text:none
spec:css-align-3; type:value; for:align-self; text:center
spec:css2; type:dfn; text:stacking context
spec:css-backgrounds-3; type:property;
	text:border-left-width
	text:border-right-width
	text:border-top-width
	text:border-bottom-width
</pre>

<style type="text/css">
	.switch > dt { font: inherit; }

	#abspos-auto ul { list-style-type: none; margin: 0; }
	#abspos-auto caption { caption-side: bottom; }

</style>

<pre class=anchors>
urlPrefix: https://www.w3.org/TR/CSS2/visuren.html; spec: CSS2;
	url: #normal-flow; text: normal flow; type: dfn;
	url: #x1; text: viewport; type: dfn;
</pre>

<pre class=link-defaults>
spec: css-align-3; type: value; text: stretch
</pre>

<h2 id="intro">
Introduction</h2>

	<em>This section is not normative.</em>

	The CSS layout algorithms, by default,
	size and position boxes in relation to each other
	so that nothing overlaps.

	This specification defines several ways to violate these assumptions when needed,
	moving elements around in ways that can make them overlap other content:

	* [=Relative positioning=], which visually shifts a box relative to its laid-out location.
	* [=Sticky positioning=], which visually shifts a box relative to its laid-out location
		in order to keep it visible when a scrollable ancestor
		would otherwise scroll it out of sight.
	* [=Absolute positioning=], which ignores normal layout entirely,
		pulling the element [=out of flow=] and
		positioning it relative to its [=containing block=]
		with no regard for other content.
	* [=Fixed positioning=], which absolutely positions the box
		and affixes it to the viewport or page frame
		so that it is always visible.

	These [=positioning schemes=],
	controlled by the 'position' property and the [=inset properties=],
	are powerful
	but easy to misuse.
	With appropriate care,
	they allow many interesting and useful layouts
	that couldn't otherwise be achieved with standard layout rules;
	without, they allow a page to be laid out in an unusable overlapping jumble of content.

<h3 id="placement">
Module Interactions</h3>

	This module replaces and extends the [=positioning scheme=] features
	defined in [[!CSS2]] sections:

	<ul>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#containing-block">9.1.2 Containing blocks</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#positioning-scheme">9.3 Positioning schemes</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#relative-positioning">9.4.3 Relative positioning</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#absolute-positioning">9.6 Absolute positioning</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#dis-pos-flo">9.7 Relationships between display, position, and float</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visuren.html#comparison">9.8 Comparison of normal flow, floats, and absolute positioning</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visudet.html#containing-block-details">10.1 Definition of "containing block"</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width">10.3.7 Absolutely positioned, non-replaced elements</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visudet.html#abs-replaced-width">10.3.8 Absolutely positioned, replaced elements</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height">10.6.4 Absolutely positioned, non-replaced elements</a>
		<li>
		<a href="https://www.w3.org/TR/CSS2/visudet.html#abs-replaced-height">10.6.5 Absolutely positioned replaced elements</a>
	</ul>

	It also replaces and supersedes the 'inset*' property definitions in [[CSS-LOGICAL-1]]
	([[CSS-LOGICAL-1#inset-properties]]).

<h3 id="values">
Value Definitions</h3>

	This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from [[!CSS2]]
	using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from [[!CSS-VALUES-3]].
	Value types not defined in this specification are defined in CSS Values &amp; Units [[!CSS-VALUES-3]].
	Combination with other CSS modules may expand the definitions of these value types.

	In addition to the property-specific values listed in their definitions,
	all properties defined in this specification
	also accept the <a>CSS-wide keywords</a> as their property value.
	For readability they have not been repeated explicitly.


<h2 id="position-property">
Choosing A Positioning Scheme: 'position' property</h2>

	<pre class="propdef">
	Name: position
	Value: static | relative | absolute | sticky | fixed
	Initial: static
	Applies to: all elements except table-column-group and table-column
	Inherited: no
	Percentages: N/A
	Computed value: specified keyword
	Animation type: discrete
	</pre>

	The 'position' property determines which of the <dfn export lt="positioning scheme">positioning schemes</dfn>
	is used to calculate the position of a box.
	Values other than ''static'' make the box a <dfn export lt="positioned box|positioned">positioned box</dfn>,
	and cause it to establish an <dfn export>absolute positioning containing block</dfn> for its descendants.
	Values have the following meanings:

<dl dfn-for="position" dfn-type="value">
	<dt><dfn>static</dfn>
	<dd>
		The box is not a [=positioned box=],
		and is laid out according to the rules of its parent [=formatting context=].
		The [=inset properties=] do not apply.

	<dt><dfn>relative</dfn>
	<dd>
		The box is laid out as for ''static'',
		then offset from the resulting position.
		This offsetting is a purely visual effect,
		and, unless otherwise specified,
		does not affect the size or position of any other non-descendant box
		except insofar as it increases the [=scrollable overflow area=] of its ancestors.
		This [=positioning scheme=] is called
		<dfn export dfn for="" lt="relative position | relatively position | relatively-positioned | relatively positioned box" local-lt="relative|relatively">relative positioning</dfn>.

	<dt><dfn>sticky</dfn>
	<dd>
		Identical to ''relative'',
		except that its offsets are automatically adjusted
		in reference to the nearest ancestor [=scroll container's=] [=scrollport=]
		(as modified by the [=inset properties=])
		in whichever axes the [=inset properties=] are not both ''top/auto'',
		to try to keep the box in view within its [=containing block=]
		as the user scrolls.
		This [=positioning scheme=] is called
		<dfn export dfn for="" lt="sticky position | sticky-positioned | sticky-positioned box" local-lt="sticky">sticky positioning</dfn>.

	<dt><dfn>absolute</dfn>
	<dd>
		The box is taken [=out of flow=]
		such that it has no impact on the size or position of its siblings and ancestors,
		and does not participate in its parent’s [=formatting context=].

		Instead, the box is positioned and sized solely in reference to
		its [=absolute positioning containing block=],
		as modified by the box's [=inset properties=],
		see [[#abspos-layout]].
		It can overlap [=in-flow=] content
		or other [=absolutely positioned=] elements,
		and is included in the [=scrollable overflow area=]
		of the box that generates is [=containing block=].
		This [=positioning scheme=] is called
		<dfn export dfn for="" lt="absolute position | absolutely position | absolutely-positioned | absolutely positioned box | absolutely positioned element" local-lt="absolute|absolutely">absolute positioning</dfn>.

	<dt><dfn>fixed</dfn>
	<dd>
		Same as ''absolute'',
		except the box is positioned and sized relative to a [=fixed positioning containing block=]
		(usually the [=viewport=] in [=continuous media=], or the [=page area=] in [=paged media=]).
		The box’s position is fixed with respect to this reference rectangle:
		when attached to the [=viewport=]
		it does not move when the document is scrolled,
		and when attached to the [=page area=]
		is replicated on every page when the document is paginated.
		This [=positioning scheme=] is called
		<dfn export dfn for="" lt="fixed position | fixed-positioned | fixed-positioned box" local-lt="fixed">fixed positioning</dfn>
		and is considered a subset of [=absolute positioning=].

		<div class="example">
			Authors may wish to specify ''fixed'' in a media-dependent way.
			For instance, an author may want a box to remain at the top of the <a>viewport</a> on the screen,
			but not at the top of each printed page.
			The two specifications may be separated by using an <a href="https://www.w3.org/TR/CSS2/media.html#at-media-rule">'@media'</a> rule, as in:

			<pre highlight=css>
			@media screen {
					h1#first { position: fixed }
			}
			@media print {
					h1#first { position: static }
			}
			</pre>
		</div>
</dl>

	A 'position' value of ''position/absolute'' or ''position/fixed''
	[=blockifies=] the box,
	causes 'float' to compute to ''float/none'',
	and forces the box to [=establish an independent formatting context=].

<h3 id="def-cb">
Containing Blocks of Positioned Boxes</h3>

	The [=containing block=] of a ''position/static'', ''position/relative'', or ''position/sticky'' [=box=]
	is as defined by its [=formatting context=].
	For ''position/fixed'' and ''position/absolute'' boxes,
	it is defined as follows:

	<dl class=switch>
		<dt id="absolute-cb">If the box has ''position: absolute'':
		<dd>
			The [=containing block=] is established
			by the nearest ancestor box that establishes an [=absolute positioning containing block=],
			in the following way:

			<dl class=switch>
				<dt>If the ancestor is not an [=inline box=],
				<dd>
					the [=containing block=] is formed by the [=padding edge=] of the ancestor,
					unless otherwise specified
					(for example, see [[CSS-GRID-1#abspos-items]]).

				<dt>If the ancestor is an [=inline box=],
					using the [=writing mode=] of that box,
				<dd>
					the [=containing block=] is formed by forming a rectangle from
					the [=start=]-most [=content edges=] (in both axes) of the first [=box fragment=] of the ancestor,
					and the [=end=]-most [=content edges=] of the [=end=]-most [=box fragment=](s) of the ancestor in each axis.
					If there are multiple fragments on the same line
					(e.g. due to [[css-writing-modes-3#bidi-box-model|bidi reordering]]),
					take the [=start=]-most fragment
					as the first fragment.

					ISSUE(8284): What is a useful containing block to form
					when the box is fragmented across multiple lines?

					Note: The [=containing block=] formed by a fragmented [=inline box=]
					was undefined in [[CSS2]].
			</dl>

			If no ancestor establishes one,
			the [=absolute positioning containing block=] is
			the [=initial containing block=].

			Note: Properties that can cause a box to establish
			an [=absolute positioning containing block=] include
			'position', 'transform', 'will-change', 'contain'&hellip;

		<dt id="fixed-cb">If the box has ''position: fixed'':
		<dd>
			The [=containing block=] is established
			by the nearest ancestor box that establishes an <dfn export>fixed positioning containing block</dfn>,
			with the bounds of the [=containing block=]
			determined identically to the [=absolute positioning containing block=].

			Note: Properties that can cause a box to establish
			a [=fixed positioning containing block=] include
			'transform', 'will-change', 'contain'&hellip;

			If no ancestor establishes one,
			the box's [=fixed positioning containing block=]
			is the <dfn export>initial fixed containing block</dfn>:

			* in [=continuous media=],
				the [=layout viewport=]
				(whose size matches the [=dynamic viewport size=]);
				as a result, [=fixed=] boxes do not move when the document is scrolled.

				Note: In this respect, they are similar to
				[[css-backgrounds-3#background-attachment|fixed background images]]
				(''background-attachment: fixed'').

			* in [=paged media=],
				the [=page area=] of each page;
				[=fixed positioned=] [=boxes=] are thus replicated on every page.
				(They are fixed with respect to the page box only,
				and are not affected by being seen through a [=viewport=];
				as in the case of print preview, for example.)

			Note: As a result, parts of [=fixed-positioned boxes=]
			that extend outside the [=layout viewport=]/[=page area=]
			cannot be scrolled to
			and will not print.

			The [=initial fixed containing block=]
			is the parent of the [=initial containing block=]
			in the [=containing block chain=].
	</dl>

<div class="example">

	With no positioning, the containing blocks (C.B.) in the following document:

	<pre highlight=html>
		&lt;!DOCTYPE html>
		&lt;html>
				&lt;head>
						&lt;title>Illustration of containing blocks&lt;/title>
				&lt;/head>
				&lt;body id="body">
						&lt;div id="div1">
						&lt;p id="p1">This is text in the first paragraph...&lt;/p>
						&lt;p id="p2">This is text &lt;em id="em1"> in the
						&lt;strong id="strong1">second&lt;/strong> paragraph.&lt;/em>&lt;/p>
						&lt;/div>
				&lt;/body>
		&lt;/html>
	</pre>

	are established as follows:

	<table class="data">
		<tr><th>For box generated by <th>C.B. is established by
		<tr><td>html<td>initial C.B. (UA-dependent)
		<tr><td>body<td>html
		<tr><td>div1<td>body
		<tr><td>p1<td>div1
		<tr><td>p2<td>div1
		<tr><td>em1<td>p2
		<tr><td>strong1<td>p2
	</table>

	If we position "div1":

	<pre highlight=css>
		#div1 { position: absolute; left: 50px; top: 50px }
	</pre>

	its containing block is no longer "body"; it becomes the <span>initial containing block</span>
	(since there are no other positioned ancestor boxes).

	If we position "em1" as well:

	<pre highlight=css>
		#div1 { position: absolute; left: 50px; top: 50px }
		#em1	{ position: absolute; left: 100px; top: 100px }
	</pre>

	the table of containing blocks becomes:

	<table class="data">
		<tr><th>For box generated by <th>C.B. is established by
		<tr><td>html<td>initial C.B. (UA-dependent)
		<tr><td>body<td>html
		<tr><td>div1<td>initial C.B.
		<tr><td>p1<td>div1
		<tr><td>p2<td>div1
		<tr><td>em1<td>div1
		<tr><td>strong1<td>em1
	</table>

	By positioning "em1", its containing block becomes the nearest positioned ancestor box
	(i.e., that generated by "div1").
</div>

<h4 id="original-cb">
Further Adjustments to the Containing Block</h4>

	Some features can alter the effective [=containing block=] rectangle
	of [=absolutely positioned=] boxes.
	These are applied in the following order,
	with earlier steps modifying the [=containing block=]
	that later steps see:

	1. The [=grid-placement properties=]
		on an [=absolutely positioned box=]
		whose [=containing block=] is generated by a [=grid container=]
		can change the [=containing block=] rectangle
		to a specified [=grid area=].
		See [[css-grid-1#abspos-items]].

	2. The 'position-area' and 'position-try' properties
		can change the [=containing block=] rectangle
		to a specified area of an [=position-area grid=].
		See [[css-anchor-position-1#position-area]].

	The element's <dfn export>original containing block</dfn>
	is its [=containing block=]
	before applying any of these effects.

<h3 id="stacking">
Painting Order and Stacking Contexts</h3>

	The 'z-index' property applies to all [=positioned boxes=].
	When 'z-index' is ''z-index/auto'':

	* [=fixed positioned|Fixed=] and [=sticky positioned|sticky=] [=positioned boxes=]
		nonetheless form a [=stacking context=].
	* [=relative positioned|Relative=] and [=absolute positioned|absolute=] [=positioned boxes=]
		do not form a [=stacking context=],
		but are painted as if those elements did generated new [=stacking contexts=],
		except that their [=positioned=] descendants and any would-be child [=stacking contexts=]
		take part in the current [=stacking context=].

	Note: The [=root element=] always forms a [=stacking context=] regardless.

	See <a href="https://www.w3.org/TR/CSS2/visuren.html#layers">CSS2 &sect; 9.9 
	Layered presentation</a>
	and <a href="https://www.w3.org/TR/CSS2/zindex.html">Appendix E: 
	Elaborate description of Stacking Contexts</a>
	for details about 'z-index', [=stacking contexts=], and painting order.

<h2 id="coords">
Positioning Coordinates</h2>

	The precise location of a [=positioned box=] is controlled by
	the <dfn>inset properties</dfn>:
	the [=physical=] [=inset properties=] 'top', 'right', 'bottom', 'left';
	the [=flow-relative=] [=inset properties=] 'inset-block-start', 'inset-inline-start', 'inset-block-end', and 'inset-inline-end';
	and their [=shorthands=], 'inset-block', 'inset-inline', and 'inset'.

	The interpretation of these [=inset properties=] varies by [=positioning scheme=]:

	* for [=absolute positioning=], they represent
		insets from the containing block.
	* for [=relative positioning=], they represent
		insets from the box’s original margin edge.
	* for [=sticky positioning=], they represent
		insets from the [=scrollport=] edge.

<h3 id="insets">
Box Insets: the 'top', 'right', 'bottom', 'left', 'inset-block-start', 'inset-inline-start', 'inset-block-end', and 'inset-inline-end' properties </h3>

	<pre class="propdef">
	Name: top, right, bottom, left, inset-block-start, inset-inline-start, inset-block-end, inset-inline-end
	Value: auto | <<length-percentage>>
	Initial: auto
	Applies to: positioned elements
	Inherited: no
	Logical property group: inset
	Percentages: refer to size of <a>containing block</a>; see prose
	Computed value: the keyword ''top/auto'' or a computed <<length-percentage>> value
	Animation type: by computed value type
	</pre>

	These [=inset properties=] represent an inward “inset”
	on the corresponding side of the box
	(with respect to the box’s own [=writing mode=];
	see [[CSS-WRITING-MODES-3#abstract-box]]).
	For example, 'top' represents a downward inset of the top edge.
	The [=physical=] and [=flow-relative=] properties
	interact as defined in [[!CSS-LOGICAL-1]].
	Values have the following meanings:

	<dl dfn-for="top,right,bottom,left, inset-block-start,inset-inline-start,inset-block-end,inset-inline-end,inset-block,inset-inline,inset" dfn-type="value">
		<dt><dfn>&lt;length></dfn>
		<dd>
			The inset is a fixed distance from the reference edge.
			Negative values are allowed.

		<dt><dfn>&lt;percentage></dfn>
		<dd>
			The inset is a percentage
			relative to the <a>containing block</a>’s size
			in the corresponding axis
			(e.g. width for 'left' or 'right', height for 'top' and 'bottom').
			For [=sticky positioned=] boxes,
			the inset is instead
			relative to the relevant [=scrollport=]’s size.
			Negative values are allowed.

		<dt><dfn>auto</dfn></dt>
		<dd>
			Represents an unconstrained inset;
			the exact meaning depends on the [=positioning scheme=].
	</dl>

	Note: For [=fixed positioned=] elements,
	using large values or negative values
	can easily move elements outside the <a>viewport</a>
	and make the contents unreachable through scrolling or other means.

<h3 id="inset-shorthands">
Box Insets Shorthands: the 'inset-block', 'inset-inline', and 'inset' properties</h3>

	<pre class="propdef">
	Name: inset-block, inset-inline
	Value: <<'top'>>{1,2}
	Initial: auto
	Applies to: positioned elements
	Inherited: no
	Percentages: see individual properties
	Computed value: see individual properties
	Animation type: by computed value type
	</pre>

	The 'inset-block' and 'inset-inline' properties are [=shorthand properties=]
	for setting 'inset-block-start' + 'inset-block-end'
	or 'inset-inline-start' + 'inset-inline-end',
	respectively,
	in a single declaration.
	The first component value sets the [=CSS/start=] side,
	the second sets the [=CSS/end=];
	if omitted, the second value defaults to the first.

	<pre class="propdef">
	Name: inset
	Value: <<'top'>>{1,4}
	Initial: auto
	Applies to: positioned elements
	Inherited: no
	Percentages: see individual properties
	Computed value: see individual properties
	Animation type: by computed value type
	</pre>

	The 'inset' property is a [=shorthand property=]
	that sets all of the [=inset properties=]
	in a single declaration,
	assigning values to the longhands representing each side
	exactly as the 'margin' property does for its longhands.

	<div class=note>

		By default, the 'inset' property values
		are assigned to the corresponding <em>[=physical=]</em> [=longhand properties=]--
		'top', 'right', 'bottom', and 'left'--
		which for historical reasons do not have an <css>inset-</css> prefix.
		This matches the behavior of other "4 values assigned to sides" properties,
		such as 'margin'.

		Allowing properties such as this to resolve to the [=flow-relative=] [=longhands=] is under discussion in [[CSS-LOGICAL-1]].

		Yes, we understand it's a little confusing
		that 'inset' doesn't expand to any 'inset-*' properties.
	</div>



<h3 id="relpos-insets" oldids="relpos">
Relative Positioning</h3>

	For a [=relatively positioned=] box,
	the [=inset properties=] move the box inward
	from the respective edge,
	without changing its size.
	'left' moves the box to the right, 'right' moves it to the left, etc.
	Since boxes are not split or stretched as a result of [=relative positioning=]
	opposing [=used values=] in a given axis must be negations of each other:

	<ul>
		<li>
			If opposing [=inset properties=] in an axis both compute to ''top/auto''
			(their [=initial values=]),
			their [=used values=] are zero
			(i.e., the boxes stay in their original position in that axis).

		<li>
			If only one is ''top/auto'',
			its [=used value=] becomes the negation of the other,
			and the box is shifted by the specified amount.

		<li>
			If neither is ''top/auto'',
			the position is over-constrained;
			(with respect to the [=writing mode=] of its [=containing block=])
			the [=computed value|computed=] [=CSS/end=] side value is ignored,
			and its [=used value=] becomes the negation of the [=CSS/start=] side.
	</ul>


	<div class="example">

		The following three rules are equivalent,
		and shift the box ''1em'' to the left:

		<pre highlight=css>
		div.a8 { position: relative; direction: ltr; left: -1em; right: auto }
		div.a8 { position: relative; direction: ltr; left: auto; right: 1em }
		div.a8 { position: relative; direction: ltr; left: -1em; right: 5em }
		</pre>
	</div>

	If specified on
	a ''table-row-group'', ''table-header-group'', ''table-footer-group'', or ''table-row'' [=box=]
	the shift affects all the contents of the box,
	including all <a value lt="table-cell">table cells</a> that originate in the affected row,
	but not those that don't.

	Note: Since 'position' does not apply to ''table-column-group'' or ''table-column'' boxes,
	they are not affected by [=relative positioning=].



<h3 id="stickypos-insets" oldids="sticky-pos">
Sticky positioning</h3>

	[=Sticky positioning=] is similar to [=relative positioning=]
	except the offsets are automatically calculated
	in reference to the [=nearest scrollport=].

	For a [=sticky positioned=] [=box=],
	the [=inset properties=]
	represent insets from the respective edges of the [=nearest scrollport=],
	defining the <dfn export>sticky view rectangle</dfn>
	used to constrain the box’s position.
	(For this purpose an ''top/auto'' value represents a zero inset.)
	If this results in a [=sticky view rectangle=] size in any axis
	less than the size of the [=border box=] of the [=sticky=] box in that axis,
	then the effective [=end=]-edge inset in the affected axis is reduced
	(possibly becoming negative)
	to bring the [=sticky view rectangle=]’s size up to
	the size of the [=border box=] in that axis
	(where [=end=] is interpreted relative to the [=writing mode=] of the [=containing block=]).

	<div class=example>
		For example,
		if the [=nearest scrollport=] is ''300px'' tall,
		the [=sticky=] box's [=border box=] is ''200px'' tall,
		and it has ''top: 20px'',
		then the top-edge inset of the [=nearest scrollport=] is ''20px'',
		and the bottom-edge inset is ''0px'',
		yielding a [=sticky view rectangle=] that is ''280px'' tall.

		But if the [=nearest scrollport=] were only ''100px'' tall,
		then the effective bottom-edge inset becomes ''-120px'',
		resulting in a [=sticky view rectangle=] that’s ''200px'' tall,
		enough to fully contain the [=margin box=] of the [=sticky=] box.
	</div>

	For each side of the box,
	if the corresponding [=inset property=] is not ''top/auto'',
	and the corresponding [=border edge=] of the box would be outside
	the corresponding edge of the [=sticky view rectangle=],
	then the box must be visually shifted
	([[#relpos-insets|as for relative positioning]])
	to be inward of that [=sticky view rectangle=] edge,
	insofar as it can while its [=position box=]
	remains contained within its [=containing block=].
	The <dfn>position box</dfn> is its [=margin box=],
	except that for any side for which the distance between its [=margin edge=]
	and the corresponding edge of its [=containing block=]
	is less than its corresponding [=margin=],
	that distance is used in place of that [=margin=].

	Note: A sticky positioned element with
	a non-''auto'' 'top' value and an ''auto'' 'bottom' value
	will only ever be pushed down by sticky positioning;
	it will never be offset upwards.

	Note: Multiple [=sticky positioned=] boxes in the same container
	are offset independently,
	and therefore might overlap.

<h4 id="stickypos-scroll">
Scroll Position of Sticky-Positioned Boxes</h4>

	For the purposes of any operation targeting the scroll position
	of a sticky positioned element (or one of its descendants),
	the sticky positioned element must be considered to be
	at its offsetted position.

	<div class="example">
		For example, if a user clicks a link targeting a [=sticky-positioned=] element,
		if the element's [=nearest scrollport=] is currently scrolled
		such that the [=sticky positioned=] element is offset from its initial position,
		the [=scroll container=] will be scrolled back
		only the minimum necessary to bring it into its desired position in the [=scrollport=]
		(rather than scrolling all the way back
		to target its original, non-offsetted position).
	</div>


<h3 id="abspos-insets" oldids="abs-pos,fixed-pos">
Absolute (and Fixed) Positioning</h3>

	For an [=absolutely positioned=] box,
	the [=inset properties=] effectively reduce the [=containing block=]
	into which it is sized and positioned
	by the specified amounts.
	The resulting rectangle is called the <dfn export>inset-modified containing block</dfn>.
	(For disambiguation, the actual [=containing block=] of an [=absolutely positioned box=]
	can also be called the <dfn export>absolute-position containing block</dfn>.)

<h4 id="resolving-insets">
Resolvings Insets for the “Inset-Modified Containing Block”</h4>

	If only one [=inset property=] in a given axis is ''top/auto'',
	it is set to zero.
	If both [=inset properties=] in a given axis are ''top/auto'', then,
	depending on the box’s [=self-alignment property=] in the relevant axis:

	<dl class=switch>
		<dt>for ''align-self/self-start'' alignment or its equivalent
		<dd>
			Set its start-edge [=inset property=] to the [=static position=],
			and its end-edge [=inset property=] to zero.

		<dt>for ''align-self/self-end'' alignment or its equivalent
		<dd>
			Set its end-edge [=inset property=] to the [=static position=],
			and its start-edge [=inset property=]  to zero.

		<dt>for ''align-self/center'' alignment
		<dd>
			Let <var>start distance</var> be the distance from
			the center of its [=static-position rectangle=]
			to the start edge of its [=containing block=],
			and <var>end distance</var> be the distance from
			the center of its [=static-position rectangle=]
			to the end edge of its [=containing block=].
			If <var>start distance</var> is less than or equal to <var>end distance</var>,
			then set the start-edge [=inset property=] to zero,
			and set the end-edge [=inset property=] to
			(<var>containing block size</var> - 2 &times; |<var>start distance</var>|);
			otherwise,
			set the end-edge [=inset property=] to zero
			and the start-edge [=inset property=] to
			(<var>containing block size</var> - 2 &times; |<var>end distance</var>|).
	</dl>

	For the rules above,
	ignore [=overflow alignment=],
	and treat ''align-self/normal'' as ''align-self/start''
	and any [=baseline alignment|baseline=] or ''align-self/stretch'' alignment value
	as its fallback alignment.

	If these adjustments result in
	an effective [=containing block=] size in any axis less than zero,
	then the [=weaker inset=] in the affected axis
	is reduced (possibly becoming negative)
	to bring that size up to zero.
	In the case that only one inset is ''auto'',
	that is the <dfn>weaker inset</dfn>
	(whose opposite inset is the <dfn>stronger inset</dfn>);
	otherwise the [=weaker inset=] is the inset of the [=end=] edge
	(where [=end=] is interpreted relative to the [=writing mode=] of the [=containing block=]).

	Note: Sizing and positioning of the [=absolutely positioned box=]
	into this [=inset-modified containing block=]
	is as described in [[#abspos-layout]].

	If its [=self-alignment property=] in an axis is ''align-self/normal'',
	then the [=resolved value=] of its [=weaker inset=] in that axis
	is the value necessary to match that edge of its [=inset-modified containing block=]
	to the corresponding edge of its [=margin box=]
	after [[#abspos-layout|layout]].
	(Otherwise the [=resolved value=] is the [=used value=] described above.)


<h4 id="staticpos-rect">
Calculating the Static Position and the “Static-Position Rectangle”</h4>

	When both [=inset properties=] in a given axis are ''left/auto'',
	they are resolved into a <dfn export>static position</dfn>
	by aligning the box into its <dfn export>static-position rectangle</dfn>,
	an [=alignment container=] derived
	from the [=formatting context=] the box would have participated in
	if it were ''position: static''
	(independent of its actual containing block).
	The [=static position=] represents
	an approximation of the position the box would have had
	if it were ''position: static''.

	<dl>
		<dt>Block Layout
		<dd>
			The [=static positions=] of a [=block-level box=]
			are defined in [[CSS2]] Chapter 10.
			The [=static-position rectangle=] is a zero-thickness rectangle spanning between
			the inline-axis sides of the box’s [=static-position containing block=]
			and positioned at its [=block-start=] [=static position=]
			(see <a href="https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height">CSS2&sect;10.6.4</a>).

			Note: In block layout the [=static-position rectangle=] corresponds to the position of the “hypothetical box”
			described in <a href="https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width">CSS2.1&sect;10.3.7</a>.
			Since it has no alignment properties,
			CSS2.1 always uses a <a>block-start</a> <a>inline-start</a> alignment
			of the absolutely-positioned box within the <a>static-position rectangle</a>.

		<dt>Inline Layout
		<dd>
			The [=static positions=] of an [=inline-level box=]
			are defined in [[CSS2]] Chapter 10.
			The [=static-position rectangle=] is a zero-thickness rectangle spanning between
			the [=line-over=]/[=line-under=] sides of the [=line box=]
			that would have contained its “hypothetical box”
			(see <a href="https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width">CSS2&sect;10.3.7</a>);
			and positioned at its [=inline-start=] [=static position=].

		<dt>Flex Layout
		<dd>
			The [=static-position rectangle=] of the child of a [=flex container=]
			corresponds to the [=content edges=] of the [=flex container=] in the [=cross axis=],
			and to the [=outer edges=] of its hypothetical position in the [=main axis=].
			See <a href="https://www.w3.org/TR/css-flexbox-1/#abspos-items">static position of a flex container child</a> in [[!CSS-FLEXBOX-1]].

		<dt>Grid Layout
		<dd>
			By default, the [=static-position rectangle=] of the child of a [=grid container=]
			corresponds to the [=content edges=] of the [=grid container=].
			However, if that [=grid container=] also establishes
			the box’s actual [=containing block=],
			then the [=grid area=] specified by the [=grid-placement properties=]
			establishes its [=static-position rectangle=] instead.
			See the <a href="https://www.w3.org/TR/css-grid-1/#static-position">static position of a grid container child</a> in [[!CSS-GRID-1]].
	</dl>

	Finding the [=static position=] and the [=static-position rectangle=]
	assumes that both 'float' and 'clear' (as well as 'position')
	have their [=initial values=],
	and can consequently require assuming a different hypothetical value
	for 'display' as well.
	(The [=containing block=] the element would have had under these conditions
	is the <dfn export>static-position containing block</dfn>.)
	To the extent the [=box alignment properties=] have an effect,
	they use the [=static-position containing block=]
	as the effective [=containing block=],
	including using its [=writing mode=] for resolving alignment axes and directions.
	Additionally, the [=containing block=] of [=fixed positioned=] elements
	is assumed to be the [=initial containing block=] instead of the [=viewport=],
	and all [=scroll containers=] should be assumed
	to be scrolled to their [=initial scroll position=].
	Lastly, all ''margin/auto'' margins on the box itself
	are treated as zero.

	Boxes in the [=top layer=] always use the [=initial containing block=]
	as their [=static-position rectangle=].

<h4 id="abspos-breaking" oldids="breaking">
Fragmenting Absolutely-positioned Elements</h4>

	In a [=fragmented flow=], an [=absolutely positioned box=]
	is positioned relative to its [=containing block=]
	ignoring any [=fragmentation breaks=]
	(as if the flow were continuous).
	The box may subsequently be broken over several [=fragmentation containers=].

	For absolutely positioned content in [=paged media=]
	that resolves to a position on a page
	other than the page being laid out (the current page),
	or resolves to a position on the current page
	that has already been rendered for printing,
	printers may place the content:

	<ul>
		<li>on the current page,
		<li>on a subsequent page, or
		<li>may omit it altogether.
	</ul>

	Note: A [=block-level=] element that is split over several pages
	can have a different width on each page,
	and there may be device-specific limits.

	User agents must not paginate the content of [=fixed-positioned boxes=].

	Note: User agents might print invisible content in other ways.
	See [[CSS-PAGE-3#content-outside-box]].

<h2 id="abspos-layout">
Absolute Positioning Layout Model</h2>

	[=Absolute positioning=] not only takes a box [=out of flow=],
	but also lays it out in its [=containing block=]
	(after the final size of the [=containing block=] has been determined)
	according to the <dfn export lt="absolute positioning layout | absolute positioning layout model">absolute positioning layout model</dfn>:

	<ol>
		<li>
			First, its [=inset-modified containing block=] is calculated,
			defining its [=available space=].
			(See [[#abspos-insets]].)

			Because an [=absolutely positioned box=] does not affect the size of its [=containing block=],
			its [=available space=] is always [=definite=].
		<li>
			Next, its width and height are resolved against this [=definite=] [=available space=],
			as its [=preferred size=] capped by its [=maximum size=] (if any), floored by its [=minimum size=].
			See [[#abspos-auto-size]].
			Percentages, however,
			are resolved against the [=absolute-position containing block=] size.

		<li>
			Then, the value of any ''margin/auto'' margins are calculated,
			see [[#abspos-margins]].

		<li>
			Lastly, its [=margin box=] is aligned within the [=inset-modified containing block=],
			see [[#abspos-alignment]].
	</ol>

<h3 id="abspos-auto-size">
Automatic Sizes of Absolutely-Positioned Boxes</h3>

	The [=automatic size=] of an [=absolutely positioned box=]
	is resolved against its [=inset-modified containing block=] as follows:

	<dl class=switch>
		: If its [=self-alignment property=] in the relevant axis is ''align-self/stretch''
			and neither of its [=inset properties=] nor [=margins=] in that axis are ''margin/auto''
		: Or if it is ''align-self/normal''
			and the box is [=non-replaced=],
			not a [=table wrapper box=],
			and has no ''inset/auto'' [=inset property|inset=] in the relevant axis
		::
			Its [=automatic size=] is its [=stretch-fit size=].

		: Otherwise
		::
			Its [=automatic size=] is its [=fit-content size=].
	</dl>

	However, if the box has an aspect-ratio,
	then an [=automatic size=] in the [=ratio-dependent axis=]
	is instead resolved as a [=max-content size=].
	When both axes have an [=automatic size=],
	if only one axis has an ''inset/auto'' [=inset property|inset=]
	then that axis is the [=ratio-dependent axis=],
	else the [=block axis=] is the [=ratio-dependent axis=].
	An [=automatic size=] in the [=ratio-determining axis=]
	is determined as above.

	For the purpose of computing these sizes,
	any ''margin/auto'' [=margins=] are treated as zero.

	The [=automatic minimum size=] of an absolutely-positioned box is always zero.

	Note: To the extent that form controls can be resized
	(and are not directly representing [=replaced elements=] such as images),
	they are expected to be treated as [=non-replaced=] here.
	In HTML, all form controls
	other than <code>&lt;input type=image></code>
	are treated as [=non-replaced=].

<h3 id="abspos-margins">
Auto Margins of Absolutely-Positioned Boxes</h3>

	If either [=inset property=] in the relevant axis is ''top/auto'',
	then any ''margin/auto'' [=margins=] resolve to zero.

	Otherwise, the <var>remaining space</var> is calculated
	as the size of its [=inset-modified containing block=] in the relevant axis
	minus the box's used size in the relevant axis,
	and this <var>remaining space</var> is divided among
	any ''margin/auto'' margins in the relevant axis.
	However,
	(all with respect to the [=writing mode=] of the [=containing block=]),
	if in the [=inline axis=]
	the <var>remaining space</var> is negative
	and both margins are ''margin/auto'',
	the [=inline-start|start=] margin resolves to zero
	and the [=inline-end|end=] margin receives the <var>remaining space</var>.

	Note: Unlike typical [=in-flow=] layout,
	the space distributed to ''margin/auto'' [=margins=]
	can be negative in [=absolute positioning=].

	ISSUE(11478): What should happen in “negatively-sized” containing blocks?
	CSS2.1 and this draft currently conflict.

<h2 id=abspos-alignment>
Self-Alignment of Absolutely Positioned Boxes</h2>

	If the [=computed value=] of either [=inset property=] in an axis is ''inset/auto'',
	then its [=margin box=] is aligned to the edge of the [=inset-modified containing block=]
	corresponding to its [=stronger inset=]
	(even if this would overflow its [=containing block=]).

	Otherwise, if either [=margin=] is ''margin/auto'',
	its position is resolved according to [[#abspos-margins]].

	Otherwise, the box is aligned as specified by
	its [=self-alignment property=] in the relevant axis
	(as defined by the [=writing mode=] of the [=containing block=]),
	using its [=margin box=] as the [=alignment subject=]
	and the [=inset-modified containing block=] as the [=alignment container=].
	However, if an explicit [=overflow alignment=] is not specified
	and its [=margin box=] overflows the [=inset-modified containing block=],
	its alignment is adjusted to minimize overflow
	as specified in [[css-align-3#auto-safety-position]].

<h2 id="abspos-old">
Old Absolute Positioning Layout Model</h2>

	ISSUE: This section is being replaced with the new [[#abspos-layout]] section.
	It is preserved here for comparison:
	both models should yield the same result
	in [=horizontal writing modes=] when the box’s [=self-alignment=] is ''align-self/normal''.

<h3 id="abs-non-replaced-width">
The Width of Absolutely-Positioned, Non-Replaced Elements</h3>

	The constraint that determines the used values for these elements is:

	<code>
		'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
		'padding-right' + 'border-right-width' + 'margin-right' +
		'right' = width of containing block
	</code>

	If all three of 'left', 'width', and 'right' are ''left/auto'':
	First set any ''margin/auto'' values for 'margin-left' and 'margin-right'
	to ''0''.
	Then, if the 'direction' property of
	the element establishing the static-position <a>containing block</a>
	is ''ltr'' set 'left' to the static position
	and apply rule number <em>three</em> below;
	otherwise, set 'right' to the static-position
	and apply rule number <em>one</em> below.

	If none of the three is ''left/auto'':
	If both 'margin-left' and 'margin-right' are ''margin/auto'',
	solve the equation under the extra constraint that
	the two margins get equal values,
	unless this would make them negative,
	in which case when direction of the containing block is ''ltr'' (''rtl''),
	set 'margin-left' ('margin-right') to ''0''
	and solve for 'margin-right' ('margin-left').
	If one of 'margin-left' or 'margin-right' is ''margin/auto'',
	solve the equation for that value.
	If the values are over-constrained,
	ignore the value for 'left'
	(in case the 'direction' property of the <a>containing block</a> is ''rtl'')
	or 'right'
	(in case 'direction' is ''ltr'') and solve for that value.

	Otherwise,
	set ''margin/auto'' values for 'margin-left' and 'margin-right' to ''0'',
	and pick one of the following six rules that apply.

	<ol>
		<li>
		If 'left' and 'width' are ''left/auto'' and 'right' is not ''right/auto'',
		then the width is shrink-to-fit.
		Then solve for 'left'.

		<li>
		If 'left' and 'right' are ''left/auto'' and 'width' is not ''width/auto'',
		then if the 'direction' property of
		the element establishing the static-position <a>containing block</a>
		is ''ltr''
		set 'left' to the static-position,
		otherwise set 'right' to the static-position.
		Then solve for 'left' (if 'direction' is ''rtl'')
		or 'right' (if 'direction' is ''ltr'').

		<li>
		If 'width' and 'right' are ''width/auto'' and 'left' is not ''left/auto'',
		then the width is shrink-to-fit.
		Then solve for 'right'.

		<li>
		If 'left' is ''left/auto'', 'width' and 'right' are not ''width/auto'',
		then solve for 'left'.

		<li>
		If 'width' is ''width/auto'', 'left' and 'right' are not ''left/auto'',
		then solve for 'width'.

		<li>
		If 'right' is ''right/auto'', 'left' and 'width' are not ''left/auto'',
		then solve for 'right'.
	</ol>

<table class=data id='abspos-auto'>
	<caption>
		Summary of rules for <code>dir=ltr</code> in horizontal writing modes
	</caption>
	<colgroup span=5></colgroup>
	<colgroup span=1></colgroup>
	<thead>
		<tr>
			<th colspan=5>Is auto?
			<th rowspan=2>Result
		<tr>
			<th>'left'
			<th>'width'
			<th>'right'
			<th>'margin-left'
			<th>'margin-right'
	<tbody>
		<tr>
			<td>✔
			<td>✔
			<td>✔
			<td colspan=2>any
			<td>
				<ul>
					<li>auto margins → zero
					<li>left → static pos
					<li>width → shrink-to-fit
					<li>right → solve
				</ul>
		<tr>
			<td rowspan=4>✘
			<td rowspan=4>✘
			<td rowspan=4>✘
			<td>✔
			<td>✘
			<td rowspan=2>
				auto margin → free space
		<tr>
			<td>✘
			<td>✔
		<tr>
			<td>✔
			<td>✔
			<td>
				<ul>
					<li>margins split positive free space
					<li>right margin gets negative free space
				</ul>
		<tr>
			<td>✘
			<td>✘
			<td>
				treat 'right' as ''right/auto''
		<tr>
			<td>✔
			<td>✘
			<td>✔
			<td colspan=2>any
			<td>
				<ul>
					<li>auto margins → zero
					<li>left → static pos
					<li>width → as specified
					<li>right → solve
				</ul>
		<tr>
			<td>✔
			<td>✔
			<td>✘
			<td colspan=2>any
			<td>
				<ul>
					<li>auto margins → zero
					<li>left → solve
					<li>width → shrink-to-fit
					<li>right → as specified
				</ul>
		<tr>
			<td>✘
			<td>✔
			<td>✔
			<td colspan=2>any
			<td>
				<ul>
					<li>auto margins → zero
					<li>left → as specified
					<li>width → shrink-to-fit
					<li>right → solve
				</ul>
		<tr>
			<td>✔
			<td>✘
			<td>✘
			<td colspan=2 rowspan=3>any
			<td rowspan=3>
				<ul>
					<li>auto margins → zero
					<li>solve for auto
				</ul>
		<tr>
			<td>✘
			<td>✘
			<td>✔
		<tr>
			<td>✘
			<td>✔
			<td>✘
</table>


<h3 id="abs-replaced-width">
The width of absolute or fixed positioned, replaced elements</h3>

	If 'height' and 'width' both have computed values of <css>auto</css>
	and the element also has an intrinsic width,
	then that intrinsic width is the used value of 'width'.

	If 'height' and 'width' both have computed values of <css>auto</css>
	and the element has no intrinsic width,
	but does have an intrinsic height and intrinsic ratio;
	or if 'width' has a computed value of <css>auto</css>,
	'height' has some other computed value,
	and the element does have an intrinsic ratio;
	then the used value of 'width' is:

	<code>(used height) * (intrinsic ratio)</code>

	If 'height' and 'width' both have computed values of <css>auto</css>,
	the element has an intrinsic ratio but no intrinsic height or width,
	and the <a>containing block’s</a> width
	does not itself depend on the replaced element’s width,
	then the used value of 'width' is calculated
	from the constraint equation used for
	<a href="https://www.w3.org/TR/CSS21/visudet.html#blockwidth">block-level, non-replaced elements in <a>normal flow</a></a>.

	Otherwise, if 'width' has a computed value of <css>auto</css>,
	and the element has an intrinsic width,
	then that intrinsic width is the used value of 'width'.

	Otherwise, if 'width' has a computed value of <css>auto</css>,
	but none of the conditions above are met,
	and then the used value of 'width' becomes ''300px''.
	If ''300px'' is too wide to fit the device,
	user agents should use the width of the largest rectangle
	that has a 2:1 ratio and fits the device instead.

	After establishing the 'width',
	in order to position the replaced element,
	apply the following rules as appropriate.

	<ol>
		<li>
		If both 'left' and 'right' have the value <css>auto</css>,
		and if the 'direction' property of
		the element establishing the static-position <a>containing block</a>
		is ''ltr'',
		set 'left' to the static position and solve for 'right';
		else if 'direction' is ''rtl'',
		set 'right' to the static position and solve for 'left'.

		<li>
		If 'left' is <css>auto</css> and 'right' is not <css>auto</css>,
		replace any <css>auto</css> on 'margin-left' or 'margin-right'
		with ''0'',
		then solve for 'left'.

		<li>
		If 'right' is <css>auto</css> and 'left' is not <css>auto</css>,
		replace any <css>auto</css> on 'margin-left' or 'margin-right'
		with ''0'',
		then solve for 'right'.

		<li>
		If at this point both 'margin-left' and 'margin-right'
		are still <css>auto</css>,
		solve the equation under the extra constraint
		that the two margins must get equal values,
		unless this would make them negative,
		in which case when the direction of the <a>containing block</a>
		is ''ltr'' (''rtl''),
		set 'margin-left' ('margin-right') to ''0''
		and solve for 'margin-right' ('margin-left').

		<li>
		If at this point there is an <css>auto</css> remaining,
		solve the equation for that value.

		<li>
		If at this point the values are over-constrained,
		ignore the value for either 'left'
		(in case the 'direction' property of the <a>containing block</a> is ''rtl'')
		or 'right' (in case 'direction' is ''ltr'')
		and solve for that value.
	</ol>

<h3 id="abs-non-replaced-height">
The Height Of Absolutely Positioned, Non-Replaced Elements</h3>

	For absolutely positioned elements,
	the used values of the vertical dimensions
	must satisfy this constraint:

	<code>
		'top' + <span>'margin-top'</span> + <span>'border-top-width'</span> + <span>'padding-top'</span> + 'height' +
		<span>'padding-bottom'</span> + <span>'border-bottom-width'</span> + <span>'margin-bottom'</span> + 'bottom'
		= <span>height of containing block</span>
	</code>

	If all three of 'top', 'height', and 'bottom' are ''top/auto'':
	First set any ''top/auto'' values for 'margin-top' and 'margin-bottom' to ''0'',
	then set 'top' to the static position,
	and finally apply rule number <em>three</em> below.

	If none of the three are ''top/auto'':
	If both 'margin-top' and 'margin-bottom' are ''top/auto'',
	solve the equation under the extra constraint that the two margins get equal values.
	If one of 'margin-top' or 'margin-bottom' is ''top/auto'',
	solve the equation for that value.
	If the values are over-constrained,
	ignore the value for 'bottom' and solve for that value.

	Otherwise,
	set ''top/auto'' values for 'margin-top' and 'margin-bottom' to ''0'',
	and pick one of the following six rules that apply.

	1. If 'top' and 'height' are ''top/auto''
		and 'bottom' is not ''top/auto'',
		then the height is based on the
		<a href="https://www.w3.org/TR/CSS2/visudet.html#root-height">Auto heights for block formatting context roots</a>,
		and solve for 'top'.

	2. If 'top' and 'bottom' are ''top/auto''
		and 'height' is not ''top/auto'',
		then set 'top' to the static position,
		then solve for 'bottom'.

	3. If 'height' and 'bottom' are ''top/auto''
		and 'top' is not ''top/auto'',
		then the height is based on the
		<a href="https://www.w3.org/TR/CSS2/visudet.html#root-height">Auto heights for block formatting context roots</a>,
		and solve for 'bottom'.

	4. If 'top' is ''top/auto'',
		'height' and 'bottom' are not ''top/auto'',
		then solve for 'top'.

	5. If 'height' is ''top/auto'',
		'top' and 'bottom' are not ''top/auto'',
		then solve for 'height'.

	6. If 'bottom' is ''top/auto'',
		'top' and 'height' are not ''top/auto'',
		then solve for 'bottom'.

<h3 id="abs-replaced-height">
The Height Of Absolutely Positioned, Replaced Elements</h3>

	If 'height' and 'width' both have computed values of ''top/auto''
	and the element also has an intrinsic height,
	then that intrinsic height is the used value of 'height'.

	Otherwise, if 'height' has a computed value of ''top/auto''
	and the element has an intrinsic ratio
	then the used value of 'height' is:

	<code>(used width) / (intrinsic ratio)</code>

	Otherwise, if 'height' has a computed value of ''top/auto''
	and the element has an intrinsic height,
	then that intrinsic height is the used value of 'height'.

	Otherwise, if 'height' has a computed value of ''top/auto'',
	but none of the conditions above are met,
	then the used value of 'height' must be set to
	the height of the largest rectangle that has a 2:1 ratio,
	has a height not greater than ''150px'',
	and has a width not greater than the device width.

	After establishing the 'height',
	in order to position the replaced element,
	apply the following rules as appropriate.

	1. If both 'top' and 'bottom' have the value ''top/auto'',
		replace 'top' with the element’s static position.

	2. If 'bottom' is ''top/auto'',
		replace any ''top/auto'' on 'margin-top' or 'margin-bottom'
		with ''0''.

	3. If at this point both 'margin-top' and 'margin-bottom' are still ''top/auto'',
		solve the equation under the extra constraint
		that the two margins must get equal values.

	4. If at this point there is only one ''top/auto'' remaining,
		solve the equation for that value.

	5. If at this point the values are over-constrained,
		ignore the value for 'bottom' and solve for that value.

<h2 id="comparison">
Informative Comparison of Normal Flow, Floats, and Positioning</h2>

	<em>This section is not normative.</em>

	To illustrate the differences between <a>normal flow</a>,
	[=relative positioning=], [=floats=], and [=absolute positioning=],
	we provide a series of examples based on the following HTML:

	<div class="example">
		<pre class="lang-html">
		&lt;!DOCTYPE html>
		&lt;html>
				&lt;head>
						&lt;title>Comparison of positioning schemes&lt;/title>
						&lt;style>
							body { display: block; font-size:12px; line-height: 200%;
											width: 400px; height: 400px }
							p		{ display: block }
							span { display: inline }
						&lt;/style>
				&lt;/head>
				&lt;body>
				&lt;p>
						Beginning of p contents.
						&lt;span id="outer"> Start of outer contents.
						&lt;span id="inner"> Inner contents.&lt;/span>
						End of outer contents.&lt;/span>
						End of p contents.
				&lt;/p>
				&lt;/body>
		&lt;/html>
		</pre>
	</div>

	The final positions of boxes generated by the <em>outer</em> and <em>inner</em>
	elements vary in each example. In each illustration, the numbers to the left of
	the illustration indicate the <a>normal flow</a> position of the
	double-spaced (for clarity) lines.

	Note: The diagrams in this section are illustrative and not to scale. They are
	meant to highlight the differences between the various <a>positioning
	schemes</a>, and are not intended to be reference renderings of the
	examples given.

<h3 id="comp-normal-flow">
Normal Flow Example</h3>

	Consider the following CSS declarations for <em>outer</em> and <em>inner</em>
	that do not alter the <a>normal flow</a> of boxes:

	<div class="example">
		<pre class="lang-css">
			#outer { color: red }
			#inner { color: blue }
		</pre>
	</div>

	The P element contains all inline content: <a href="https://www.w3.org/TR/CSS2/visuren.html#anonymous">anonymous inline text</a> and
	two SPAN elements. Therefore, all of the content will be laid out in an inline
	formatting context, within a <a>containing block</a> established by the P element, producing
	something like:

<figure>
	<img src="images/flow-generic.png" alt="Image illustrating the normal flow of text between parent and sibling boxes.">
	<figcaption>
		All of the text within the P's containing block flows together as continuous text,
		even though it's located in separated nested elements.
	</figcaption>
</figure>

<h3 id="comp-relpos">
Relative Positioning Example</h3>

	To see the effect of <a>relative positioning</a>,
	we specify:

	<div class="example">
		<pre class="lang-css">
		#outer { position: relative; top: -12px; color: red }
		#inner { position: relative; top: 12px; color: blue }
		</pre>
	</div>

	Text flows normally up to the <em>outer</em> element. The <em>outer</em> text is
	then flowed into its <a>normal flow</a> position and dimensions at the end of line 1. Then,
	the inline boxes containing the text (distributed over three lines) are shifted as a
	unit by ''-12px'' (upwards).

	The contents of <em>inner</em>, as a child of <em>outer</em>, would normally flow
	immediately after the words "of outer contents" (on line 1.5). However, the <em>inner</em>
	contents are themselves offset relative to the <em>outer</em> contents by ''12px''
	(downwards), back to their original position on line 2.

	<p class="note">
		Note that the content following <em>outer</em> is not affected by the relative
		positioning of <em>outer</em>.
	</p>

	<figure>
		<img src="images/flow-relative.png">
		<figcaption>
			The result is identical to normal flow,
			except that the "outer" text is shifted 12px upward,
			without affecting the flow of the "body" or "inner" text.
		</figcaption>
	</figure>

	<p class="note">
		Note also that had the offset of <em>outer</em> been ''-24px'', the text	of <em>outer</em>
		and the body text would have overlapped.
	</p>

<h3 id="comp-floating">
Floating Example</h3>

	Now consider the effect of <a href="https://www.w3.org/TR/CSS2/visuren.html#floats">
	floating</a> the <em>inner</em> element’s text to the right by means of the
	following rules:

	<div class="example">
		<pre class="lang-css">
		#outer { color: red }
		#inner { float: right; width: 130px; color: blue }
		</pre>
	</div>

	Text flows normally up to the <em>inner</em> box, which is pulled out of the flow
	and <a>floated</a> to the right margin (its 'width' has been
	assigned explicitly). Line boxes to the left of the float are shortened, and the
	document’s remaining text flows into them.

<figure>
	<img src="images/flow-float.png" alt="Image illustrating the effects of floating a box.">
	<figcaption>
		The "inner" text lays out in an independent box on the right,
		causing the remaining "body" and "outer" text to flow around it.
	</figcaption>
</figure>

	To show the effect of the 'clear' property, we add a <em>sibling</em> element to the
	example:

	<div class="example">
		<pre class="lang-html">
		&lt;!DOCTYPE html>
		&lt;html>
				&lt;head>
						&lt;title>Comparison of positioning schemes II&lt;/title>
						&lt;style>
							#inner { float: right; width: 130px; color: blue }
							#sibling { color: red }
						&lt;/style>
				&lt;/head>
				&lt;body>
				&lt;p>
						Beginning of p contents.
						&lt;span id="outer"> Start of outer contents.
						&lt;span id="inner"> Inner contents.&lt;/span>
						&lt;span id="sibling"> Sibling contents.&lt;/span>
						End of outer contents.&lt;/span>
						End of p contents.
				&lt;/p>
				&lt;/body>
		&lt;/html>
		</pre>
	</div>

	These styles cause the <em>inner</em> box to float to the right, as before,
	and the document’s remaining text to flow into the vacated space:

	<figure>
		<img src="images/flow-clear.png" alt="Image illustrating the effects of floating a box without setting the clear property to control the flow of text around the box.">
		<figcaption>
			Identical to the previous example,
			save that there is now "sibling" text
			flowing with the "body" and "outer" text.
		</figcaption>
	</figure>

	However, if the 'clear' property on the <em>sibling</em> element is set to 'right'
	(i.e., the generated <em>sibling</em> box will not accept a position next to
	<a>floating</a> boxes to its right), the <em>sibling</em> content begins to flow below the
	float:

	<div class="example">
		<pre class="lang-css">
		#inner { float: right; width: 130px; color: blue }
		#sibling { clear: right; color: red }
		</pre>
	</div>

	<figure>
		<img src="images/flow-clear2.png" alt="Image illustrating the effects of floating an element with setting the clear property to control the flow of text around the element.">
		<figcaption>
			Now the "sibling" text moves down to below the "inner" text’s box,
			leaving blank space behind.
			The text following the "sibling" text flows after it as normal.
		</figcaption>
	</figure>

<h3 id="comp-abspos">
Absolute Positioning Example</h3>

	Next, we consider the effect of absolute positioning. Consider the following CSS
	declarations for <em>outer</em> and <em>inner</em>:

	<div class="example">
		<pre class="lang-css">
		#outer {
				position: absolute;
				top: 200px; left: 200px;
				width: 200px;
				color: red;
		}
		#inner { color: blue }
		</pre>
	</div>

	which cause the top of the <em>outer</em> box to be positioned with respect to its
	<a>containing block</a>. The <a>containing block</a> for a positioned box is established by the
	nearest positioned ancestor (or, if none exists, the <span>initial containing block</span>, as in
	our example). The top side of the <em>outer</em> box is ''200px'' below the top of the
	<a>containing block</a> and the left side is ''200px'' from the left side. The child box of
	<em>outer</em> is flowed normally with respect to its parent.

	<figure>
		<img src="images/flow-absolute.png" alt="Image illustrating the effects of absolutely positioning a box.">
		<figcaption>
			All of the text within #outer (the "outer" and "inner" text)
			moves down to an independent box in the lower right corner.
			The two halves of "body" text flow together.
		</figcaption>
	</figure>

	The following example shows an absolutely positioned box that is a child of a relatively
	positioned box. Although the parent <em>outer</em> box is not actually offset, setting
	its 'position' property to ''position/relative'' means that its box may serve as the containing
	block for positioned descendants. Since the <em>outer</em> box is an inline box that is
	split across several lines, the first inline box’s top and left edges (depicted by thick
	dashed lines in the illustration below) serve as references for 'top' and 'left' offsets.

	<div class="example">
		<pre class="lang-css">
		#outer {
				position: relative;
				color: red
		}
		#inner {
				position: absolute;
				top: 200px; left: -100px;
				height: 130px; width: 130px;
				color: blue;
		}
		</pre>
	</div>

	This results in something like the following:

	<figure>
		<img src="images/flow-abs-rel.png" alt="Image illustrating the effects of absolutely positioning a box with respect to a containing block.">
		<figcaption>
			The "inner" text is positioned in an independent box,
			relative to the top-left corner of the start of the "outer" text.
		</figcaption>
	</figure>

	If we do not position the <em>outer</em> box:

	<div class="example">
		<pre class="lang-css">
		#outer { color: red }
		#inner {
				position: absolute;
				top: 200px; left: -100px;
				height: 130px; width: 130px;
				color: blue;
		}
		</pre>
	</div>

	the <a>containing block</a> for <em>inner</em> becomes the <span>initial
	containing block</span> (in our example). The following illustration shows where
	the <em>inner</em> box would end up in this case.

	<figure>
		<img src="images/flow-static.png" alt="Image illustrating the effects of absolutely positioning a box with respect to a containing block established by a normally positioned parent.">
		<figcaption>
			Same as before,
			except now the "inner text" is positioned relative to the top-left corner of the page itself.
		</figcaption>
	</figure>

	Relative and absolute positioning may be used to implement change bars, as shown
	in the following example. The following fragment:

	<div class="example">
		<pre class="lang-html">
		&lt;p style="position: relative; margin-right: 10px; left: 10px;">
			I used two red hyphens to serve as a change bar. They
			will "float" to the left of the line containing THIS
			&lt;span style="position: absolute; top: auto; left: -1em; color: red;">--&lt;/span>
			word.
		&lt;/p>
		</pre>
	</div>

	might result in something like:

	<figure>
		<img src="images/changebar.png" alt="Image illustrating the use of floats to create a changebar effect.">
		<figcaption>
			The two red hyphens, indicating a change,
			sit in the left margin of the page
			on the line containing the word "THIS",
			regardless of what line that ends up being.
		</figcaption>
	</figure>

	First, the paragraph (whose <a>containing block</a> sides are shown in the
	illustration) is flowed normally. Then it is offset ''10px'' from the left edge
	of the <a>containing block</a> (thus, a right margin of ''10px'' has been
	reserved in anticipation of the offset). The two hyphens acting as change bars
	are taken out of the flow and positioned at the current line (due to 'top: auto'),
	''-1em'' from the left edge of its containing block (established by the P in
	its final position).	The result is that the change bars seem to "float" to the
	left of the current line.

<h2 id="ack">
Acknowledgments</h2>

	This module would not have been possible without input and support from many
	helpful people. Thanks to
	Rossen Atanassov,
	Bert Bos,
	Oriol Brufau,
	Tantek &Ccedil;elik,
	Arron Eicholz
	Sylvain Galineau,
	John Jansen,
	Chris Jones,
	Ian Kilpatrick,
	Anton Prowse.


<h2 class="no-num" id="changes">Changes</h2>


	Significant changes since the <a href="https://www.w3.org/TR/2025/WD-css-position-3-20250311/">11 March 2025 Working Draft</a>:

	* Defined the [=initial fixed containing block=] and its relationship to the [=initial containing block=],
		to give this concept a name.

	See also <a href="https://www.w3.org/TR/2025/WD-css-position-3-20250311/#changes">Previous Changes</a>.

<h2 class=no-num id=privacy>
Privacy Considerations</h2>

This specification introduces no new privacy considerations.

<h2 class=no-num id=security>
Security Considerations</h2>

If an attacker is able to inject arbitrary CSS,
positioned layout can make it easier to position elements the attacker has control of
over arbitrary other elements of the page,
potentially tricking users of the page.
(There are many routes to this attack: negative 'margin', 'transform', etc.
Don't let people apply arbitrary CSS to bits of your page.)

''position: fixed'' can allow a page to emulate modal dialogs,
potentially tricking a user into thinking they're interacting with the user agent
and entering in sensitive information that they page can then capture.
User agents must ensure that their native dialogs are positioned
in ways that the page cannot emulate;
in particular,
that at least some of the dialog is outside the "poisoned pixels" that web content can paint to.
